package org.opensourceway.sbom.model.pojo.vo.sbom;

import org.apache.commons.lang3.StringUtils;
import org.opensourceway.sbom.model.entity.VulScore;
import org.opensourceway.sbom.model.entity.Vulnerability;
import org.opensourceway.sbom.model.enums.CvssSeverity;
import org.opensourceway.sbom.model.enums.VulScoringSystem;
import org.springframework.data.util.Pair;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

public class VulnerabilityVo implements Serializable {

    private String vulId;

    private String scoringSystem;

    private Double score;

    private String vector;

    private String severity;

    private List<Pair<String, String>> references;

    private String purl;

    private String affectedBranchesUnRepair;

    private String affectedRepository;

    private String affectedBranchesOpen;

    private String affectedBranches;

    private String notAnalyzedBranches;

    private String affectedBranchesRepair;

    public String getAffectedBranchesUnRepair() {
        return affectedBranchesUnRepair;
    }

    public void setAffectedBranchesUnRepair(String affectedBranchesUnRepair) {
        this.affectedBranchesUnRepair = affectedBranchesUnRepair;
    }

    public String getAffectedRepository() {
        return affectedRepository;
    }

    public void setAffectedRepository(String affectedRepository) {
        this.affectedRepository = affectedRepository;
    }

    public String getAffectedBranchesOpen() {
        return affectedBranchesOpen;
    }

    public void setAffectedBranchesOpen(String affectedBranchesOpen) {
        this.affectedBranchesOpen = affectedBranchesOpen;
    }

    public String getAffectedBranches() {
        return affectedBranches;
    }

    public void setAffectedBranches(String affectedBranches) {
        this.affectedBranches = affectedBranches;
    }

    public String getNotAnalyzedBranches() {
        return notAnalyzedBranches;
    }

    public void setNotAnalyzedBranches(String notAnalyzedBranches) {
        this.notAnalyzedBranches = notAnalyzedBranches;
    }

    public String getAffectedBranchesRepair() {
        return affectedBranchesRepair;
    }

    public void setAffectedBranchesRepair(String affectedBranchesRepair) {
        this.affectedBranchesRepair = affectedBranchesRepair;
    }

    public String getVulId() {
        return vulId;
    }

    public void setVulId(String vulId) {
        this.vulId = vulId;
    }

    public String getScoringSystem() {
        return scoringSystem;
    }

    public void setScoringSystem(String scoringSystem) {
        this.scoringSystem = scoringSystem;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }

    public String getVector() {
        return vector;
    }

    public void setVector(String vector) {
        this.vector = vector;
    }

    public String getSeverity() {
        return severity;
    }

    public void setSeverity(String severity) {
        this.severity = severity;
    }

    public List<Pair<String, String>> getReferences() {
        return references;
    }

    public void setReferences(List<Pair<String, String>> references) {
        this.references = references;
    }

    public String getPurl() {
        return purl;
    }

    public void setPurl(String purl) {
        this.purl = purl;
    }

    public static VulnerabilityVo fromVulnerability(Vulnerability vulnerability) {
        VulnerabilityVo vo = new VulnerabilityVo();

        vo.setVulId(vulnerability.getVulId());
        inferAndSetScore(vo, vulnerability);
        vo.setReferences(vulnerability.getVulReferences().stream().map(ref -> Pair.of(ref.getType(), ref.getUrl())).toList());
        return vo;
    }

    public static void inferAndSetScore(VulnerabilityVo vo, Vulnerability vulnerability) {
        List<VulScore> scores = vulnerability.getVulScores();
        if (scores.size() == 1) {
            vo.setScoringSystem(scores.get(0).getScoringSystem());
            vo.setScore(scores.get(0).getScore());
            vo.setVector(scores.get(0).getVector());
            vo.setSeverity(scores.get(0).getSeverity());
        } else if (scores.size() > 1) {
            VulScore cvss3 = scores.stream()
                    .filter(score -> StringUtils.equals(score.getScoringSystem(), VulScoringSystem.CVSS_V3.name()))
                    .findFirst()
                    .orElse(null);
            VulScore cvss2 = scores.stream()
                    .filter(score -> StringUtils.equals(score.getScoringSystem(), VulScoringSystem.CVSS_V2.name()))
                    .findFirst()
                    .orElse(null);

            if (Objects.nonNull(cvss3)) {
                vo.setScoringSystem(cvss3.getScoringSystem());
                vo.setScore(cvss3.getScore());
                vo.setVector(cvss3.getVector());
                vo.setSeverity(cvss3.getSeverity());
            } else if (Objects.nonNull(cvss2)) {
                vo.setScoringSystem(cvss2.getScoringSystem());
                vo.setScore(cvss2.getScore());
                vo.setVector(cvss2.getVector());
                vo.setSeverity(cvss2.getSeverity());
            }
        } else {
            vo.setSeverity(CvssSeverity.UNKNOWN.name());
        }
    }

}
